package ch13.optional;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) throws IOException {
        var contents = Files.readString(
            Path.of("ch09/set/alice30.txt")
        );
        var wordList = List.of(contents.split("\\PL+"));

        var optionalValue = wordList.stream().filter(s -> s.contains("freq")).findFirst();
        System.out.println(optionalValue.orElse("No word") + " contains fred");

        var optionalString = Optional.empty();
        var result = optionalString.orElse("N/A");
        System.out.println("result: " + result);

        result = optionalString.orElseGet(() -> Locale.getDefault().getDisplayName());
        System.out.println("result: " + result);

        try {
            result = optionalString.orElseThrow(IllegalStateException::new);
            System.out.println("result: " + result);
        } catch (Throwable t) {
            t.printStackTrace();
        }

        optionalValue = wordList.stream().filter(s -> s.contains("red")).findFirst();
        optionalValue.ifPresent(s -> System.out.println(s + " contains red"));

        var results = new HashSet<String>();
        optionalValue.ifPresent(results::add);

        // Optional<U> map(Function<? super T, ? extends U> mapper)
        // 返回的是Optional.of(mapper.apply(t))
        // results已经包含了"red"，所以返回Optional[false]
        var added = optionalValue.map(results::add);
        System.out.println(added);

        // flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)
        System.out.println(inverse(4.0).flatMap(OptionalTest::squareRoot));
        System.out.println(inverse(-1.0).flatMap(OptionalTest::squareRoot));
        System.out.println(inverse(0.0).flatMap(OptionalTest::squareRoot));

        Optional<Double> result2 =
            Optional.of(-4.0)
                .flatMap(OptionalTest::inverse)
                .flatMap(OptionalTest::squareRoot);
        System.out.println(result2);
    }

    public static Optional<Double> inverse(Double x) {
        return x == 0 ? Optional.empty() : Optional.of(1 / x);
    }

    public static Optional<Double> squareRoot(Double x) {
        return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
    }
}
